;*******************************************************************************
;* @item     CosyOS-III Port
;* @file     port_cmx_s.s
;* @brief    CMSIS Cortex-M Core Port File
;* @author   迟凯峰
;* @version  V1.0.1
;* @date     2025.02.15
;*******************************************************************************
;* <<< Use Configuration Wizard in Context Menu >>>
;
; <e> 是否启用thumb汇编移植方案？
; <i> 启用该方案后，如果在 mcucfg_cmx.h 中，系统中断配置为 TIMn_IRQHandler + XXX_IRQHandler，
; <i> 用户另需在下方（Line 45、46）手动修改 PendSV_Handler 为 XXX_IRQHandler。
CMXPRT_THUMB            EQU     0
;
; <o> 指令集架构
; <0=> ARMv6-M <1=> ARMv7-M
CMXPRT_ISA              EQU     1
;
; <q> 是否启用DEBUG接口并同时启用任务PC监控？
SYSCFG_TASKPC_MONITOR   EQU     1
;
; <e> 是否启用PendSV_FIFO？
CMXPRT_PENDSVFIFO       EQU     1
;
; <o> PendSV_FIFO互斥访问方案
; <1=> 互斥访问指令 <2=> 互斥访问机制 <3=> 关闭总中断
;
; <i> 方案一、互斥访问指令
; <i> 该方案仅适用于Cortex-M3/M4/M7等支持互斥访问指令[LDREX/STREX]的内核，可实现全局不关总中断、零中断延迟。
;
; <i> 方案二、互斥访问机制
; <i> 该方案适用于所有ARM内核，可实现全局不关总中断、零中断延迟。
; <i> 缺点是在默认情况下，系统会占用寄存器r7，专用于互斥访问，其它大部分函数都将无法使用r7。
; <i> 详情参见相关说明。
;
; <i> 方案三、关闭总中断
; <i> 该方案适用于所有ARM内核，并具有极短的、确定的关闭总中断时间（包括再次开启总中断在内，不超过10个指令周期）。
; <i> 该方案，内核关闭总中断仅发生在中断挂起服务装载器中的__LOAD段。
MCUCFG_PENDSVFIFO_MUTEX EQU     1
; </e>
;
; <q> 浮点寄存器上下文自动保存
; <i> 是否启用浮点寄存器的上下文自动保存功能？
; <i> 如果启用了硬件浮点单元，并且在多个任务或中断中都要进行浮点运算，应该开启该功能；
; <i> 如果仅在特定的一个任务或中断中进行浮点运算，可以关闭该功能以提高性能。
MCUCFG_ASPEN_LSPEN      EQU     0
; </e>
;
MCUCFG_CALLEE_PUSH_REG  EQU     32
;
;///////////////////////////////////////////////////////////////////////////////

                IF CMXPRT_THUMB == 1

                THUMB
                AREA    |.text|, CODE, READONLY

;///////////////////////////////////////////////////////////////////////////////

; PendSV软中断
; 如果在 mcucfg_cmx.h 中，系统中断配置为 TIMn_IRQHandler + XXX_IRQHandler，
; 需在下方手动修改 PendSV_Handler 为 XXX_IRQHandler。

PendSV_Handler  PROC                    ;用户手动修改 PendSV_Handler 为 XXX_IRQHandler
                EXPORT  PendSV_Handler  ;用户手动修改 PendSV_Handler 为 XXX_IRQHandler

                IMPORT  sPendSV_Handler
                IMPORT  s_task_current
                IMPORT  s_task_news
                PRESERVE8

                push    {lr}

                bl      sPendSV_Handler

                IF CMXPRT_ISA == 0
                cmp     r0, #0
                beq     __RETURN
                ELSE
                cbz     r0, __RETURN
                ENDIF

                isb

                ldr     r1, =s_task_current
                subs    r0, #1
                IF CMXPRT_ISA == 0
                cmp     r0, #0
                beq     __RESTORE
                ELSE
                cbz     r0, __RESTORE
                ENDIF

                mrs     r0, psp

            IF SYSCFG_TASKPC_MONITOR == 1

                IMPORT  s_sign_taskmgr
                IMPORT  s_pc
                ldr     r3, =s_sign_taskmgr
                ldrb    r3, [r3]
                IF CMXPRT_ISA == 0
                cmp     r3, #0
                beq     __PROTECTING
                ELSE
                cbz     r3, __PROTECTING
                ENDIF
                mov     r3, r0
                adds    r3, #24
                ldmia   r3, {r2}
                ldr     r3, =s_pc
                str     r2, [r3]

            ENDIF

__PROTECTING
            IF MCUCFG_ASPEN_LSPEN == 1

                vstmdb  r0!, {s16-s31}

            ENDIF

            IF CMXPRT_ISA == 0

                subs    r0, #MCUCFG_CALLEE_PUSH_REG
                ldr     r2, [r1]
                str     r0, [r2]
                stmia   r0!, {r4-r7}
                mov     r4, r8
                mov     r5, r9
                mov     r6, r10
                mov     r7, r11
                stmia   r0!, {r4-r7}

            ELSE

                stmdb   r0!, {r4-r11}
                ldr     r2, [r1]
                str     r0, [r2]

            ENDIF

__RESTORE       ldr     r3, =s_task_news
                ldr     r3, [r3]
                str     r3, [r1]
                ldr     r0, [r3]

            IF CMXPRT_ISA == 0

                adds    r0, #16
                ldmia   r0!, {r4-r7}
                mov     r11, r7
                mov     r10, r6
                mov     r9, r5
                mov     r8, r4
                mov     r1, r0
                subs    r1, #MCUCFG_CALLEE_PUSH_REG
                ldmia   r1!, {r4-r7}

            ELSE

                ldmia   r0!, {r4-r11}

            ENDIF

            IF MCUCFG_ASPEN_LSPEN == 1

                vldmia  r0!, {s16-s31}

            ENDIF

                msr     psp, r0

__RETURN        pop     {pc}

                ALIGN

                ENDP

;///////////////////////////////////////////////////////////////////////////////

; 中断挂起服务装载器

                IF CMXPRT_PENDSVFIFO == 1

mPendSV_FIFOLoader\
                PROC
                EXPORT  mPendSV_FIFOLoader

                IMPORT  mPendSV_FIFO_P0
                IMPORT  mPendSV_FIFO_P1
                IMPORT  m_sign_fifo

                ldr     r3, =m_sign_fifo
                ldrb    r3, [r3]
                IF CMXPRT_ISA == 0
                cmp     r3, #0
                beq     __FIFO1
                ELSE
                cbz     r3, __FIFO1
                ENDIF

__FIFO0         ldr     r1, =mPendSV_FIFO_P0
                b       __LOAD

__FIFO1         ldr     r1, =mPendSV_FIFO_P1

            IF MCUCFG_PENDSVFIFO_MUTEX == 1

__LOAD          ldrex   r2, [r1]
                adds    r2, #4
                strex   r3, r2, [r1]
                cmp     r3, #0
                bne     __LOAD

            ELIF MCUCFG_PENDSVFIFO_MUTEX == 2

                IMPORT  mPendSV_FIFO_P2
                IMPORT  m_sign_load

__LOAD          push    {r0, r4}
                mov     r0, r7

                ldr     r3, =m_sign_load
                ldrb    r4, [r3]
                movs    r2, #1
                strb    r2, [r3]

__LOOP          mov     r7, r1
                ldr     r2, [r7]
                adds    r2, #4
                str     r2, [r7]
                cmp     r7, r1
                bne     __LOOP

                strb    r4, [r3]

                IF CMXPRT_ISA == 0
                cmp     r4, #0
                beq     __RESR7
                ELSE
                cbz     r4, __RESR7
                ENDIF
                ldr     r7, =mPendSV_FIFO_P2
                b       __OVER
__RESR7         mov     r7, r0
__OVER          pop     {r0, r4}

            ELIF MCUCFG_PENDSVFIFO_MUTEX == 3

__LOAD          mrs     r3, primask
                cpsid   i
                ldr     r2, [r1]
                adds    r2, #4
                str     r2, [r1]
                msr     primask, r3

            ENDIF

                str     r0, [r2]
                bx      lr

                ALIGN

                ENDP

                ENDIF

;///////////////////////////////////////////////////////////////////////////////

                ENDIF

                END
